﻿using System;
using System.Windows.Forms;

namespace LightEngine
{
    namespace MessbauerCore
    {
        namespace MessbauerData
        {
            /// <описание класса public class TransformationAlgorithm>
            /// Версия класса 1.0
            /// Автор(ы): Ушаков Михаил
            /// Класс является базовым типом алгоритмов преобразования мессбауэрских спектров.
            /// 1. Константы класса:
            ///    отсутствуют.
            /// 2. Поля класса:
            /// а) private MessbSpectrum SpecTransformResult = new MessbSpectrum(); результат
            ///    преобразования мессбауэровского спектра.
            /// 3. Методы класса:
            /// а) public MessbSpectrum GetTransformationResult() получение результата преобразования 
            ///    мессбауэрского спектра, сохраненного в SpecTransformResult.
            /// б) public virtual Boolean Transform(MessbSpectrum Spec, UInt32 Param) проведение 
            ///    преобразования с ипользованием одного мессбауэрского спектра с параметром преобразования
            ///    Param и возврат результата типа Boolean (true если преобразование выполнено успешно, 
            ///    иначе false).
            /// в) public virtual Boolean Transform(MessbSpectrum Spec1, MessbSpectrum Spec2, UInt32 Param)
            ///    проведение преобразования с ипользованием одного мессбауэрского спектра с параметром преобразования
            ///    Param и возврат результата типа Boolean (true если преобразование выполнено успешно, 
            ///    иначе false).
            /// 4. Свойства и индексаторы класса:
            /// а) protected MessbSpectrum ResultingMessbauerSpectrum защищенное свойство для чтения и записи
            ///    поля SpecTransformResult, необходимо для наследующих классов.
            /// </описание класса public class TransformationAlgorithm>

            public class TransformationAlgorithm
            {
                private MessbSpectrum SpecTransformResult = new MessbSpectrum();
                public MessbSpectrum GetTransformationResult() { return SpecTransformResult; }
                public virtual Boolean Transform(MessbSpectrum Spec, UInt32 Param) { return false; }
                public virtual Boolean Transform(MessbSpectrum Spec1, MessbSpectrum Spec2,
                                                 UInt32 Param) { return false; }
                protected MessbSpectrum ResultingMessbauerSpectrum
                {
                    get { return SpecTransformResult; }
                    set { SpecTransformResult = value; }
                }
            }

            /// <описание класса public class StrippingAlgorithm : TransformationAlgorithm>
            /// Версия класса 1.0
            /// Автор(ы): Ушаков Михаил
            /// Класс является алгоритмом стриппинг преобразования мессбауэрских спектров (вычитание 
            /// относительных интенсивностей двух спектров).
            /// 1. Константы класса:
            ///    отсутствуют.
            /// 2. Поля класса:
            ///    отсутствуют.
            /// 3. Методы класса:
            /// а) public virtual Boolean Transform(MessbSpectrum Spec1, MessbSpectrum Spec2, UInt32 Param)
            ///    проведение вычитания из 1 разности относительных интенсивностей спектров Spec1 и Spec2 
            ///    (разность берется  по модулю), далее полученная разность умножается на масштабирующий 
            ///    коэффициент, заданный в Param.
            ///    Функция возвращает результат типа Boolean (true если преобразование выполнено успешно, 
            ///    иначе false).
            /// 4. Свойства и индексаторы класса:
            ///    отсутствуют.
            /// </описание класса public class StrippingAlgorithm : TransformationAlgorithm>

            public class StrippingAlgorithm : TransformationAlgorithm
            {
                public override Boolean Transform(MessbSpectrum Spec1, MessbSpectrum Spec2, UInt32 Param)
                {
                    UInt64[] Spectrum = new UInt64[(UInt16)AllowableNumOfChannels.Channel_Mode5];
                    MessbSpectrum Spec = new MessbSpectrum();

                    if (Spec1.NumOfChannels != Spec2.NumOfChannels)
                    {
                        MessageBox.Show("Стриппинг метод применим для спектров с равным числом точек", "Ошибка");
                        ResultingMessbauerSpectrum = null;
                        return false;
                    }
                    Double Result;
                    // todo: Нормировка на величину эффекта
                    //MessageBox.Show(Spec1[0].ToString(), Spec2[0].ToString());
                    Spec1.CalculateParameters(true); Spec2.CalculateParameters(true);
                    //MessageBox.Show(Spec1.MaxNumOfCounts.ToString(), Spec2.MaxNumOfCounts.ToString());
                    for (UInt16 Counter = 0; Counter < Spec1.NumOfChannels; Counter++)
                    {
                        Result = Math.Abs((Double)(Spec1[Counter]) / (Double)(Spec1.MaxNumOfCounts) -
                                          (Double)(Spec2[Counter]) / (Double)(Spec2.MaxNumOfCounts));
                        Result = 1.0 - Result;
                        Result *= (Double)Param;
                        Spectrum[Counter] = (UInt64)Result;

                    }
                    Spec.LoadSpectrum(Spectrum, Spec1.NumOfChannels);
                    ResultingMessbauerSpectrum = Spec;
                    return true;
                }
            }

            /// <описание класса public class ScalingAlgorithm : TransformationAlgorithm>
            /// Версия класса 1.0
            /// Автор(ы): Ушаков Михаил
            /// Класс является алгоритмом сжатия мессбауэрских спектров (уменьшения числа точек).
            /// 1. Константы класса:
            ///    отсутствуют.
            /// 2. Поля класса:
            ///    отсутствуют.
            /// 3. Методы класса:
            /// а) public virtual Boolean Transform(MessbSpectrum Spec1, MessbSpectrum Spec2, UInt32 Param)
            ///    проведение масштабирования спектра Spec1 (Spec2 игнорируется), масштабирующий 
            ///    коэффициент задается в Param (если он равен 2 число точек в спектре-результате 
            ///    уменьшается в 2 раза, если 4 в 4 и т.д.)
            ///    Функция возвращает результат типа Boolean (true если преобразование выполнено успешно, 
            ///    иначе false).
            /// 4. Свойства и индексаторы класса:
            ///    отсутствуют.
            /// </описание класса public class ScalingAlgorithm : TransformationAlgorithm>

            public class ScalingAlgorithm : TransformationAlgorithm
            {
                public override Boolean Transform(MessbSpectrum Spec1, MessbSpectrum Spec2, UInt32 Param)
                {
                    UInt64[] Spectrum = new UInt64[(UInt16)AllowableNumOfChannels.Channel_Mode5];
                    MessbSpectrum Spec = new MessbSpectrum();

                    AllowableNumOfChannels Check = (AllowableNumOfChannels)(UInt16)(Spec1.NumOfChannels / Param);
                    if (Enum.IsDefined(typeof(AllowableNumOfChannels), Check) == false)
                    {
                        MessageBox.Show("Преобразование невозможно", "Ошибка");
                        return false;
                    }

                    for (UInt32 Counter = 0; Counter < Spec1.NumOfChannels; Counter += Param)
                    {
                        for (UInt32 Count = 0; Count < Param; Count++)
                        {
                            Spectrum[Counter / Param] += Spec1[(UInt16)(Counter + Count)];
                        }
                    }
                    Spec.LoadSpectrum(Spectrum, (UInt16)((Double)Spec1.NumOfChannels / (Double)Param));
                    ResultingMessbauerSpectrum = Spec;
                    return true;
                }
            }

            /// <описание класса public class InvertingAlgorithm : TransformationAlgorithm>
            /// Версия класса 1.0
            /// Автор(ы): Ушаков Михаил
            /// Класс является алгоритмом инвертирования мессбауэровских спектров относительно вертикальной
            /// оси (оси числа импульсов).
            /// 1. Константы класса:
            ///    отсутствуют.
            /// 2. Поля класса:
            ///    отсутствуют.
            /// 3. Методы класса:
            /// а) public virtual Boolean Transform(MessbSpectrum Spec1, MessbSpectrum Spec2, UInt32 Param)
            ///    проведение инверсии спектра Spec1 (Spec2 игнорируется), т.е. последняя точка становится 
            ///    первой, а первая последней и т.д.
            ///    Функция возвращает результат типа Boolean (true если преобразование выполнено успешно, 
            ///    иначе false).
            /// 4. Свойства и индексаторы класса:
            ///    отсутствуют.
            /// </описание класса public class InvertingAlgorithm : TransformationAlgorithm>

            public class InvertingAlgorithm : TransformationAlgorithm
            {
                public override Boolean Transform(MessbSpectrum Spec1, MessbSpectrum Spec2, UInt32 Param)
                {
                    UInt64[] Spectrum = new UInt64[(UInt16)AllowableNumOfChannels.Channel_Mode5];
                    MessbSpectrum Spec = new MessbSpectrum();

                    for (UInt16 Counter = 0; Counter < Spec1.NumOfChannels; Counter++)
                    {
                        Spectrum[Spec1.NumOfChannels - 1 - Counter] = Spec1[Counter];
                    }

                    Spec.LoadSpectrum(Spectrum, Spec1.NumOfChannels);
                    ResultingMessbauerSpectrum = Spec;

                    return true;
                }
            }
        }
    }
}